home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises. All rights reserved.
-
- This file is part of Aladdin Ghostscript.
-
- Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- or distributor accepts any responsibility for the consequences of using it,
- or for whether it serves any particular purpose or works at all, unless he
- or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- License (the "License") for full details.
-
- Every copy of Aladdin Ghostscript must include a copy of the License,
- normally in a plain ASCII text file named PUBLIC. The License grants you
- the right to copy, modify and redistribute Aladdin Ghostscript, but only
- under certain conditions described in the License. Among other things, the
- License requires that the copyright notice and this notice be preserved on
- all copies.
- */
-
- /* gximage.c */
- /* Image setup procedures for Ghostscript library */
- #include "gx.h"
- #include "math_.h"
- #include "memory_.h"
- #include "gpcheck.h"
- #include "gserrors.h"
- #include "gsstruct.h"
- #include "gxfixed.h"
- #include "gxfrac.h"
- #include "gxarith.h"
- #include "gxmatrix.h"
- #include "gsccolor.h"
- #include "gspaint.h"
- #include "gzstate.h"
- #include "gxdevice.h"
- #include "gzpath.h"
- #include "gzcpath.h"
- #include "gxdevmem.h"
- #include "gximage.h"
- #include "gdevmrop.h"
-
- /* Structure descriptor */
- private_st_gx_image_enum();
-
- /* Strategy procedures */
- gx_image_strategies_t image_strategies;
-
- /* Define the procedures for initializing gs_image_ts to default values. */
- private void
- image_t_init(gs_image_t *pim, bool mask)
- { pim->Width = pim->Height = 0;
- gs_make_identity(&pim->ImageMatrix);
- pim->BitsPerComponent = 1;
- /* Doesn't fill in ColorSpace. */
- /* Doesn't fill in Decode. */
- pim->Interpolate = false;
- pim->ImageMask = pim->adjust = mask;
- pim->CombineWithColor = false;
- #ifdef DPNEXT
- pim->HasAlpha = false;
- #endif
- }
- void
- gs_image_t_init_mask(gs_image_t *pim, bool write_1s)
- { image_t_init(pim, true);
- pim->ColorSpace = NULL;
- if ( write_1s )
- pim->Decode[0] = 1, pim->Decode[1] = 0;
- else
- pim->Decode[0] = 0, pim->Decode[1] = 1;
- }
- void
- gs_image_t_init_gray(gs_image_t *pim)
- { image_t_init(pim, false);
- pim->ColorSpace = gs_color_space_DeviceGray();
- pim->Decode[0] = 0;
- pim->Decode[1] = 1;
- }
- void
- gs_image_t_init_color(gs_image_t *pim)
- { gs_image_t_init_gray(pim);
- pim->ColorSpace = gs_color_space_DeviceRGB();
- pim->Decode[2] = pim->Decode[4] = pim->Decode[6] = 0;
- pim->Decode[3] = pim->Decode[5] = pim->Decode[7] = 1;
- #ifdef DPNEXT
- pim->Decode[8] = 0, pim->Decode[9] = 1;
- #endif
- }
-
- /* GC procedures */
- #define eptr ((gx_image_enum *)vptr)
- private ENUM_PTRS_BEGIN(image_enum_enum_ptrs) {
- int bps;
- gs_ptr_type_t ret;
- /* Enumerate the used members of clues.dev_color. */
- index -= gx_image_enum_num_ptrs;
- bps = eptr->unpack_bps;
- if ( eptr->spp != 1 )
- bps = 8;
- else if ( bps > 8 || eptr->unpack == sample_unpack_copy )
- bps = 1;
- if ( index >= (1 << bps) * st_device_color_max_ptrs ) /* done */
- return 0;
- ret = (*st_device_color.enum_ptrs)
- (&eptr->clues[(index / st_device_color_max_ptrs) *
- (255 / ((1 << bps) - 1))].dev_color,
- sizeof(eptr->clues[0].dev_color),
- index % st_device_color_max_ptrs, pep);
- if ( ret == 0 ) /* don't stop early */
- ENUM_RETURN(0);
- return ret;
- }
- #define e1(i,elt) ENUM_PTR(i,gx_image_enum,elt);
- gx_image_enum_do_ptrs(e1)
- #undef e1
- ENUM_PTRS_END
- private RELOC_PTRS_BEGIN(image_enum_reloc_ptrs) {
- int i;
- #define r1(i,elt) RELOC_PTR(gx_image_enum,elt);
- gx_image_enum_do_ptrs(r1)
- #undef r1
- { int bps = eptr->unpack_bps;
- if ( eptr->spp != 1 )
- bps = 8;
- else if ( bps > 8 || eptr->unpack == sample_unpack_copy )
- bps = 1;
- for ( i = 0; i <= 255; i += 255 / ((1 << bps) - 1) )
- (*st_device_color.reloc_ptrs)
- (&eptr->clues[i].dev_color, sizeof(gx_device_color), gcst);
- }
- } RELOC_PTRS_END
- #undef eptr
-
- /* Forward declarations */
- private int color_draws_b_w(P2(gx_device *dev,
- const gx_drawing_color *pdcolor));
- private void image_init_map(P3(byte *map, int map_size, const float *decode));
- private void image_init_colors(P9(gx_image_enum *penum, int bps, int spp,
- bool multi, const float *decode,
- const gs_imager_state *pis, gx_device *dev,
- const gs_color_space *pcs, bool *pdcb));
-
- /* Procedures for unpacking the input data into bytes or fracs. */
- /*extern sample_unpack_proc(sample_unpack_copy);*/ /* declared above */
- extern sample_unpack_proc(sample_unpack_1);
- extern sample_unpack_proc(sample_unpack_2);
- extern sample_unpack_proc(sample_unpack_4);
- extern sample_unpack_proc(sample_unpack_8);
- sample_unpack_proc((*sample_unpack_12_proc)); /* optional */
-
- /* The image_render procedures work on fully expanded, complete rows. */
- /* These take a height argument, which is an integer >= 0; */
- /* they return a negative code, or the number of */
- /* rows actually processed (which may be less than the height). */
- /* height = 0 is a special call to indicated that the image has been */
- /* fully processed; this is necessary because the last scan lines of */
- /* the source data may not produce any output. */
-
- /* Start processing an image. */
- int
- gx_default_begin_image(gx_device *dev,
- const gs_imager_state *pis, const gs_image_t *pim,
- gs_image_format_t format, const gs_int_rect *prect,
- const gx_drawing_color *pdcolor, const gx_clip_path *pcpath,
- gs_memory_t *mem, void **pinfo)
- { gx_image_enum *penum;
- const int width = pim->Width;
- const int height = pim->Height;
- const int bps = pim->BitsPerComponent;
- bool masked = pim->ImageMask;
- const float *decode = pim->Decode;
- bool multi;
- int index_bps;
- const gs_color_space *pcs = pim->ColorSpace;
- gs_logical_operation_t lop = pis->log_op;
- int code;
- gs_matrix mat;
- int log2_xbytes = (bps <= 8 ? 0 : arch_log2_sizeof_frac);
- int spp, nplanes, spread;
- uint bsize;
- byte *buffer;
- fixed mtx, mty;
- gs_fixed_point row_extent, col_extent, x_extent, y_extent;
- bool device_color;
- gs_fixed_rect obox, cbox;
- fixed adjust;
-
- if ( width < 0 || height < 0 )
- return_error(gs_error_rangecheck);
- switch ( format )
- { case gs_image_format_chunky: multi = false; break;
- case gs_image_format_component_planar: multi = true; break;
- default: return_error(gs_error_rangecheck);
- }
- switch ( bps )
- {
- case 1: index_bps = 0; break;
- case 2: index_bps = 1; break;
- case 4: index_bps = 2; break;
- case 8: index_bps = 3; break;
- case 12: index_bps = 4; break;
- default: return_error(gs_error_rangecheck);
- }
- if ( prect )
- { if ( prect->p.x < 0 || prect->p.y < 0 ||
- prect->q.x < prect->p.x || prect->q.y < prect->p.y ||
- prect->q.x > width || prect->q.y > height
- )
- return_error(gs_error_rangecheck);
- }
- if ( (code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 ||
- (code = gs_matrix_multiply(&mat, &ctm_only(pis), &mat)) < 0 ||
- (code =
- gs_distance_transform2fixed((const gs_matrix_fixed *)&mat,
- (floatp)width, (floatp)0,
- &row_extent)) < 0 ||
- (code =
- gs_distance_transform2fixed((const gs_matrix_fixed *)&mat,
- (floatp)0, (floatp)height,
- &col_extent)) < 0
- )
- return code;
- penum = gs_alloc_struct(mem, gx_image_enum, &st_gx_image_enum,
- "gx_default_begin_image");
- if ( penum == 0 )
- return_error(gs_error_VMerror);
- if ( prect )
- { penum->rect.x = prect->p.x, penum->rect.y = prect->p.y;
- penum->rect.w = prect->q.x - prect->p.x,
- penum->rect.h = prect->q.y - prect->p.y;
- if ( (code =
- gs_distance_transform2fixed((const gs_matrix_fixed *)&mat,
- (floatp)penum->rect.w, (floatp)0,
- &x_extent)) < 0 ||
- (code =
- gs_distance_transform2fixed((const gs_matrix_fixed *)&mat,
- (floatp)0, (floatp)penum->rect.h,
- &y_extent)) < 0
- )
- { gs_free_object(mem, penum, "gx_default_begin_image");
- return code;
- }
- }
- else
- { penum->rect.x = 0, penum->rect.y = 0;
- penum->rect.w = width, penum->rect.h = height;
- x_extent = row_extent;
- y_extent = col_extent;
- }
- if ( (penum->masked = masked) )
- { /* This is imagemask. */
- if ( bps != 1 || multi || pcs != NULL ||
- #ifdef DPNEXT
- pim->HasAlpha ||
- #endif
- !((decode[0] == 0.0 && decode[1] == 1.0) ||
- (decode[0] == 1.0 && decode[1] == 0.0))
- )
- { gs_free_object(mem, penum, "gx_default_begin_image");
- return_error(gs_error_rangecheck);
- }
- /* Initialize color entries 0 and 255. */
- color_set_pure(&penum->icolor0, gx_no_color_index);
- penum->icolor1 = *pdcolor;
- memcpy(&penum->map[0].table.lookup4x1to32[0],
- (decode[0] == 0 ? lookup4x1to32_inverted :
- lookup4x1to32_identity),
- 16 * 4);
- penum->map[0].decoding = sd_none;
- spp = 1;
- adjust = (pim->adjust ? float2fixed(0.25) : fixed_0);
- lop = rop3_know_S_0(lop);
- }
- else
- { /* This is image, not imagemask. */
- const gs_color_space_type _ds *pcst = pcs->type;
- int b_w_color;
-
- spp = pcst->num_components;
- if ( spp < 0 ) /* Pattern not allowed */
- { gs_free_object(mem, penum, "gx_default_begin_image");
- return_error(gs_error_rangecheck);
- }
- #ifdef DPNEXT
- if ( pim->HasAlpha )
- ++spp;
- #endif
- if ( spp == 1 )
- multi = false;
- device_color = (*pcst->concrete_space)(pcs, pis) == pcs;
- image_init_colors(penum, bps, spp, multi, decode, pis, dev,
- pcs, &device_color);
- adjust = fixed_0;
- /* Try to transform non-default RasterOps to something */
- /* that we implement less expensively. */
- if ( !pim->CombineWithColor )
- lop = rop3_know_T_0(lop);
- else
- { if ( rop3_uses_T(lop) )
- switch ( color_draws_b_w(dev, pdcolor) )
- {
- case 0:
- lop = rop3_know_T_0(lop); break;
- case 1:
- lop = rop3_know_T_1(lop); break;
- default:
- ;
- }
- }
- if ( lop != rop3_S && /* if best case, no more work needed */
- !rop3_uses_T(lop) && bps == 1 && spp == 1 &&
- (b_w_color =
- color_draws_b_w(dev, &penum->icolor0)) >= 0 &&
- color_draws_b_w(dev, &penum->icolor1) == (b_w_color ^ 1)
- )
- { if ( b_w_color )
- { /* Swap the colors and invert the RasterOp source. */
- gx_device_color dcolor;
- dcolor = penum->icolor0;
- penum->icolor0 = penum->icolor1;
- penum->icolor1 = dcolor;
- lop = rop3_invert_S(lop);
- }
- /*
- * At this point, we know that the source pixels
- * correspond directly to the S input for the raster op,
- * i.e., icolor0 is black and icolor1 is white.
- */
- switch ( lop )
- {
- case rop3_D & rop3_S:
- /* Implement this as an inverted mask writing 0s. */
- penum->icolor1 = penum->icolor0;
- /* (falls through) */
- case rop3_D | rop3_not(rop3_S):
- /* Implement this as an inverted mask writing 1s. */
- memcpy(&penum->map[0].table.lookup4x1to32[0],
- lookup4x1to32_inverted, 16 * 4);
- rmask: /* Fill in the remaining parameters for a mask. */
- penum->masked = masked = true;
- color_set_pure(&penum->icolor0, gx_no_color_index);
- penum->map[0].decoding = sd_none;
- lop = rop3_T;
- break;
- case rop3_D & rop3_not(rop3_S):
- /* Implement this as a mask writing 0s. */
- penum->icolor1 = penum->icolor0;
- /* (falls through) */
- case rop3_D | rop3_S:
- /* Implement this as a mask writing 1s. */
- memcpy(&penum->map[0].table.lookup4x1to32[0],
- lookup4x1to32_identity, 16 * 4);
- goto rmask;
- default:
- ;
- }
- }
- }
- penum->device_color = device_color;
- /* Round up the width, +1 for an end-of-run byte. */
- bsize = ((bps > 8 ? width * 2 : width) + 8) * spp;
- buffer = gs_alloc_bytes(mem, bsize, "image buffer");
- if ( buffer == 0 )
- { gs_free_object(mem, penum, "gx_default_begin_image");
- return_error(gs_error_VMerror);
- }
- penum->bps = bps;
- penum->unpack_bps = bps;
- penum->log2_xbytes = log2_xbytes;
- penum->spp = spp;
- #ifdef DPNEXT
- penum->has_alpha = pim->HasAlpha;
- #endif
- nplanes = (multi ? spp : 1);
- penum->num_planes = nplanes;
- spread = nplanes << log2_xbytes;
- penum->spread = spread;
- penum->matrix = mat;
- penum->x_extent = x_extent;
- penum->y_extent = y_extent;
- penum->posture =
- ((x_extent.y | y_extent.x) == 0 ? image_portrait :
- (x_extent.x | y_extent.y) == 0 ? image_landscape :
- image_skewed);
- mtx = float2fixed(mat.tx);
- mty = float2fixed(mat.ty);
- penum->pis = pis;
- penum->pcs = pcs;
- penum->memory = mem;
- penum->dev = dev;
- penum->buffer = buffer;
- penum->buffer_size = bsize;
- penum->line = 0;
- penum->line_size = 0;
- #ifdef FUTURE
- /*
- * If we're asked to interpolate in a partial image, we have to
- * assume that the client either really only is interested in
- * the given sub-image, or else is constructing output out of
- * overlapping pieces.
- */
- penum->interpolate = pim->Interpolate;
- #else
- /* Interpolation in a partial image (probably) doesn't make sense. */
- penum->interpolate =
- pim->Interpolate &&
- !(penum->rect.x | penum->rect.y |
- (width - penum->rect.w) | (height - penum->rect.h));
- #endif
- penum->use_rop = lop != (masked ? rop3_T : rop3_S);
- #ifdef DEBUG
- if ( gs_debug_c('*') )
- { if ( penum->use_rop )
- dprintf1("[%03x]", lop);
- dprintf5("%c%d%c%dx%d ",
- (masked ? (color_is_pure(pdcolor) ? 'm' : 'h') : 'i'),
- bps,
- (penum->posture == image_portrait ? ' ' :
- penum->posture == image_landscape ? 'L' : 'T'),
- width, height);
- }
- #endif
- penum->slow_loop = 0;
- if ( pcpath == 0 )
- { (*dev_proc(dev, get_clipping_box))(dev, &obox);
- cbox = obox;
- penum->clip_image = 0;
- }
- else
- penum->clip_image =
- (gx_cpath_outer_box(pcpath, &obox) | /* not || */
- gx_cpath_inner_box(pcpath, &cbox) ?
- 0 : image_clip_region);
- penum->clip_outer = obox;
- penum->clip_inner = cbox;
- penum->log_op = rop3_T; /* rop device takes care of this */
- penum->clip_dev = 0; /* in case we bail out */
- penum->rop_dev = 0; /* ditto */
- penum->scaler = 0; /* ditto */
- /*
- * If all four extrema of the image fall within the clipping
- * rectangle, clipping is never required. When making this check,
- * we must carefully take into account the fact that we only care
- * about pixel centers.
- */
- { fixed
- epx = min(row_extent.x, 0) + min(col_extent.x, 0),
- eqx = max(row_extent.x, 0) + max(col_extent.x, 0),
- epy = min(row_extent.y, 0) + min(col_extent.y, 0),
- eqy = max(row_extent.y, 0) + max(col_extent.y, 0);
-
- { int hwx, hwy;
-
- switch ( penum->posture )
- {
- case image_portrait:
- hwx = width, hwy = height;
- break;
- case image_landscape:
- hwx = height, hwy = width;
- break;
- default:
- hwx = hwy = 0;
- }
- /*
- * If the image is only 1 sample wide or high,
- * and is less than 1 device pixel wide or high,
- * move it slightly so that it covers pixel centers.
- * This is a hack to work around a bug in some old
- * versions of TeX/dvips, which use 1-bit-high images
- * to draw horizontal and vertical lines without
- * positioning them properly.
- */
- if ( hwx == 1 && eqx - epx < fixed_1 )
- { fixed diff =
- arith_rshift_1(row_extent.x + col_extent.x);
- mtx = (((mtx + diff) | fixed_half) & -fixed_half) - diff;
- }
- if ( hwy == 1 && eqy - epy < fixed_1 )
- { fixed diff =
- arith_rshift_1(row_extent.y + col_extent.y);
- mty = (((mty + diff) | fixed_half) & -fixed_half) - diff;
- }
- }
- if_debug11('b',
- "[b]Image: cbox=(%g,%g),(%g,%g), obox=(%g,%g),(%g,%g)\n mt=(%g,%g) clip_image=0x%x\n",
- fixed2float(cbox.p.x), fixed2float(cbox.p.y),
- fixed2float(cbox.q.x), fixed2float(cbox.q.y),
- fixed2float(obox.p.x), fixed2float(obox.p.y),
- fixed2float(obox.q.x), fixed2float(obox.q.y),
- fixed2float(mtx), fixed2float(mty),
- penum->clip_image);
- dda_init(penum->dda.row.x, mtx, col_extent.x, height);
- dda_init(penum->dda.row.y, mty, col_extent.y, height);
- if ( penum->rect.y )
- { dda_advance(penum->dda.row.x, penum->rect.y);
- dda_advance(penum->dda.row.y, penum->rect.y);
- }
- penum->cur.x = penum->prev.x = dda_current(penum->dda.row.x);
- penum->cur.y = penum->prev.y = dda_current(penum->dda.row.y);
- dda_init(penum->dda.pixel0.x, penum->cur.x, row_extent.x,
- width);
- dda_init(penum->dda.pixel0.y, penum->cur.y, row_extent.y,
- width);
- if ( penum->rect.x )
- { dda_advance(penum->dda.pixel0.x, penum->rect.x);
- dda_advance(penum->dda.pixel0.y, penum->rect.x);
- }
- { fixed ox = dda_current(penum->dda.pixel0.x);
- fixed oy = dda_current(penum->dda.pixel0.y);
- if ( !penum->clip_image ) /* i.e., not clip region */
- penum->clip_image =
- (fixed_pixround(ox + epx) < fixed_pixround(cbox.p.x) ?
- image_clip_xmin : 0) +
- (fixed_pixround(ox + eqx) >= fixed_pixround(cbox.q.x) ?
- image_clip_xmax : 0) +
- (fixed_pixround(oy + epy) < fixed_pixround(cbox.p.y) ?
- image_clip_ymin : 0) +
- (fixed_pixround(oy + eqy) >= fixed_pixround(cbox.q.y) ?
- image_clip_ymax : 0);
- }
- }
- penum->y = 0;
- penum->adjust = adjust;
- { static sample_unpack_proc((*procs[4])) = {
- sample_unpack_1, sample_unpack_2,
- sample_unpack_4, sample_unpack_8
- };
- if ( index_bps == 4 )
- { if ( (penum->unpack = sample_unpack_12_proc) == 0 )
- { /* 12-bit samples are not supported. */
- gx_default_end_image(dev, penum, false);
- return_error(gs_error_rangecheck);
- }
- }
- else
- { penum->unpack = procs[index_bps];
- if_debug1('b', "[b]unpack=%d\n", bps);
- }
- #define use_strategy(sp)\
- (image_strategies.sp != 0 &&\
- (penum->render = (*image_strategies.sp)(penum)) != 0)
- if (
- use_strategy(interpolate) ||
- use_strategy(simple) ||
- use_strategy(fracs) ||
- use_strategy(mono) ||
- use_strategy(color)
- )
- DO_NOTHING;
- #undef use_strategy
- else
- { /* No available strategy can handle this image. */
- gx_default_end_image(dev, penum, false);
- return_error(gs_error_rangecheck);
- }
- }
- if ( penum->clip_image && pcpath )
- { /* Set up the clipping device. */
- gx_device_clip *cdev =
- gs_alloc_struct(mem, gx_device_clip,
- &st_device_clip, "image clipper");
- if ( cdev == 0 )
- { gx_default_end_image(dev, penum, false);
- return_error(gs_error_VMerror);
- }
- gx_make_clip_device(cdev, cdev, &pcpath->list);
- cdev->target = dev;
- (*dev_proc(cdev, open_device))((gx_device *)cdev);
- penum->clip_dev = cdev;
- }
- if ( penum->use_rop )
- { /* Set up the RasterOp source device. */
- gx_device_rop_texture *rtdev =
- gs_alloc_struct(mem, gx_device_rop_texture,
- &st_device_rop_texture, "image RasterOp");
- if ( rtdev == 0 )
- { gx_default_end_image(dev, penum, false);
- return_error(gs_error_VMerror);
- }
- gx_make_rop_texture_device(rtdev,
- (penum->clip_dev != 0 ?
- (gx_device *)penum->clip_dev :
- dev), lop, pdcolor);
- penum->rop_dev = rtdev;
- }
- if_debug8('b', "[b]Image: w=%d h=%d [%g %g %g %g %g %g]\n",
- width, height,
- mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
- *pinfo = penum;
- return 0;
- }
-
- /* If a drawing color is black or white, return 0 or 1 respectively, */
- /* otherwise return -1. */
- private int
- color_draws_b_w(gx_device *dev, const gx_drawing_color *pdcolor)
- { if ( color_is_pure(pdcolor) )
- { gx_color_value rgb[3];
- (*dev_proc(dev, map_color_rgb))(dev, gx_dc_pure_color(pdcolor),
- rgb);
- if ( !(rgb[0] | rgb[1] | rgb[2]) )
- return 0;
- if ( (rgb[0] & rgb[1] & rgb[2]) == gx_max_color_value )
- return 1;
- }
- return -1;
- }
-
- /* Initialize the color mapping tables for a non-mask image. */
- private void
- image_init_colors(gx_image_enum *penum, int bps, int spp, bool multi,
- const float *decode /*[spp*2]*/, const gs_imager_state *pis, gx_device *dev,
- const gs_color_space *pcs, bool *pdcb)
- { int ci;
- static const float default_decode[] =
- { 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
- #ifdef DPNEXT
- , 0.0, 1.0
- #endif
- };
-
- /* Initialize the color table */
-
- #define ictype(i)\
- penum->clues[i].dev_color.type
- switch ( (spp == 1 ? bps : 8) )
- {
- case 8: /* includes all color images */
- { register gx_image_clue *pcht = &penum->clues[0];
- register int n = 64;
- do
- { pcht[0].dev_color.type =
- pcht[1].dev_color.type =
- pcht[2].dev_color.type =
- pcht[3].dev_color.type =
- gx_dc_type_none;
- pcht[0].key = pcht[1].key =
- pcht[2].key = pcht[3].key = 0;
- pcht += 4;
- }
- while ( --n > 0 );
- penum->clues[0].key = 1; /* guarantee no hit */
- break;
- }
- case 4:
- ictype(17) = ictype(2*17) = ictype(3*17) =
- ictype(4*17) = ictype(6*17) = ictype(7*17) =
- ictype(8*17) = ictype(9*17) = ictype(11*17) =
- ictype(12*17) = ictype(13*17) = ictype(14*17) =
- gx_dc_type_none;
- /* falls through */
- case 2:
- ictype(5*17) = ictype(10*17) = gx_dc_type_none;
- #undef ictype
- }
-
- /* Initialize the maps from samples to intensities. */
-
- for ( ci = 0; ci < spp; ci++ )
- { sample_map *pmap = &penum->map[ci];
-
- /* If the decoding is [0 1] or [1 0], we can fold it */
- /* into the expansion of the sample values; */
- /* otherwise, we have to use the floating point method. */
-
- const float *this_decode = &decode[ci * 2];
- const float *map_decode; /* decoding used to */
- /* construct the expansion map */
-
- const float *real_decode; /* decoding for */
- /* expanded samples */
-
- bool no_decode;
-
- map_decode = real_decode = this_decode;
- if ( map_decode[0] == 0.0 && map_decode[1] == 1.0 )
- no_decode = true;
- else if ( map_decode[0] == 1.0 && map_decode[1] == 0.0 )
- no_decode = true,
- real_decode = default_decode;
- else
- no_decode = false,
- *pdcb = false,
- map_decode = default_decode;
- if ( bps > 2 || multi )
- { if ( bps <= 8 )
- image_init_map(&pmap->table.lookup8[0], 1 << bps,
- map_decode);
- }
- else
- { /* The map index encompasses more than one pixel. */
- byte map[4];
- register int i;
- image_init_map(&map[0], 1 << bps, map_decode);
- switch ( bps )
- {
- case 1:
- { register bits32 *p = &pmap->table.lookup4x1to32[0];
- if ( map[0] == 0 && map[1] == 0xff )
- memcpy((byte *)p, lookup4x1to32_identity, 16 * 4);
- else if ( map[0] == 0xff && map[1] == 0 )
- memcpy((byte *)p, lookup4x1to32_inverted, 16 * 4);
- else
- for ( i = 0; i < 16; i++, p++ )
- ((byte *)p)[0] = map[i >> 3],
- ((byte *)p)[1] = map[(i >> 2) & 1],
- ((byte *)p)[2] = map[(i >> 1) & 1],
- ((byte *)p)[3] = map[i & 1];
- } break;
- case 2:
- { register bits16 *p = &pmap->table.lookup2x2to16[0];
- for ( i = 0; i < 16; i++, p++ )
- ((byte *)p)[0] = map[i >> 2],
- ((byte *)p)[1] = map[i & 3];
- } break;
- }
- }
- pmap->decode_base /* = decode_lookup[0] */ = real_decode[0];
- pmap->decode_factor =
- (real_decode[1] - real_decode[0]) /
- (bps <= 8 ? 255.0 : (float)frac_1);
- pmap->decode_max /* = decode_lookup[15] */ = real_decode[1];
- if ( no_decode )
- pmap->decoding = sd_none;
- else if ( bps <= 4 )
- { int step = 15 / ((1 << bps) - 1);
- int i;
-
- pmap->decoding = sd_lookup;
- for ( i = 15 - step; i > 0; i -= step )
- pmap->decode_lookup[i] = pmap->decode_base +
- i * (255.0 / 15) * pmap->decode_factor;
- }
- else
- pmap->decoding = sd_compute;
- if ( spp == 1 ) /* and ci == 0 */
- { /* Pre-map entries 0 and 255. */
- gs_client_color cc;
- cc.paint.values[0] = real_decode[0];
- (*pcs->type->remap_color)(&cc, pcs, &penum->icolor0,
- pis, dev, gs_color_select_source);
- cc.paint.values[0] = real_decode[1];
- (*pcs->type->remap_color)(&cc, pcs, &penum->icolor1,
- pis, dev, gs_color_select_source);
- }
- }
-
- }
- /* Construct a mapping table for sample values. */
- /* map_size is 2, 4, 16, or 256. Note that 255 % (map_size - 1) == 0, */
- /* so the division 0xffffL / (map_size - 1) is always exact. */
- private void
- image_init_map(byte *map, int map_size, const float *decode)
- { float min_v = decode[0];
- float diff_v = decode[1] - min_v;
-
- if ( diff_v == 1 || diff_v == -1 )
- { /* We can do the stepping with integers, without overflow. */
- byte *limit = map + map_size;
- uint value = min_v * 0xffffL;
- int diff = diff_v * (0xffffL / (map_size - 1));
-
- for ( ; map != limit; map++, value += diff )
- *map = value >> 8;
- }
- else
- { /* Step in floating point, with clamping. */
- int i;
- for ( i = 0; i < map_size; ++i )
- { int value = (int)((min_v + diff_v * i / (map_size - 1)) * 255);
- map[i] = (value < 0 ? 0 : value > 255 ? 255 : value);
- }
- }
- }
-